<template>
  <!-- swiper容器 -->
  <div class="swiper" ref="swiperRef">
    <!-- 轮播内容 -->
    <div class="swiper-wrapper">
      <!-- 一张轮播图-->
      <div class="swiper-slide" v-for="image in imagesList" :key="image.id">
        <!-- 注意把images放到public里，因为banners数据是mock模拟的 会有路径问题404 放在public的文件会自动打包到根目录 -->

        <img :src="image.imgUrl" alt="banner" />
      </div>
    </div>
    <!-- 小圆点区域——分页器 -->
    <div class="swiper-pagination"></div>

    <!-- 左右翻页区域 -->
    <div class="swiper-button-prev"></div>
    <div class="swiper-button-next"></div>
  </div>
</template>

<script>
// 引入js
import Swiper, { Navigation, Pagination, Autoplay } from "swiper";
// 引入css
import "swiper/css";
import "swiper/css/navigation";
import "swiper/css/pagination";

export default {
  name: "XCarousel",
  // props:['imagesList'],//props写数组
  props: {
    // props写对象
    imagesList: Array,
  },

  // 在挂载完成才可以获取到dom元素
  // mounted() {

  // },
  watch: {
    imagesList: {
      handler(imagesList) {
        // console.log(imagesList);
        /*
          Home上面轮播会触发两次new Swiper
          原因：
            第一个轮播图初始化渲染没有数据，（immediate: true）触发一次
            后面请求得到数据，数据发生变化，又触发一次
            触发两次就会 new 两次 Swiper，导致轮播出现 bug
        */
        // 不进行第二次new Swiper 阻止第一次的（immediate: true）触发
        if (!imagesList.length) return;

        // 监听imagesList ，数据一改变说明imagesList有值了
        // console.log(11111,imagesList);
        
        // 1.有数据，才new Swiper
        // 2.去等用户界面渲染完成，在 new Swiper
        this.$nextTick(() => {
          // 第一个参数可以写选择器也可以写元素
          new Swiper(this.$refs.swiperRef, {
            modules: [Navigation, Pagination, Autoplay],
            // 无缝轮播
            loop: true,
            // 小圆点
            pagination: {
              el: ".swiper-pagination",
            },
            // 左右翻页
            navigation: {
              nextEl: ".swiper-button-next",
              prevEl: ".swiper-button-prev",
            },
            // 自动轮播  autoplay可以写 布尔值和对象
            autoplay: {
              delay: 1000, // 每n秒轮播一张
              pauseOnMouseEnter: true, // 鼠标移入暂停轮播
              disableOnInteraction: false, // 鼠标移除开始轮播
            },
          });
        });
      },
      immediate: true, // 开启立即监视,让监视属性第一次就触发
      // 为了解决Floor组件的轮播，开启立即监视就能监视到从数据从无到有的改变  但是会出现Home上面轮播会触发两次new Swiper
    },
  },
};
</script>

<style scoped></style>
<!-- 
按需加载
  1.安装
  2.准备HTML结构
  3.引入js
  4.引入css
  5.new Swiper({
      modules:[Navigation, Pagination, Autoplay],
      loop: true,
      pagination: {
        el: '.swiper-pagination',
      },
      navigation: {
        nextEl: '.swiper-button-next',
        prevEl: '.swiper-button-prev',
      },
      autoplay:{
        delay:1000,
        pauseOnMouseEnter:true,
        disableOnInteraction:false,
      }
  })

  无缝轮播出现问题
  - 原因：子组件 mounted 先触发，父组件 mounted 后触发，子组件先 new Swiper，此时请求都还未发送，根本没有数据，渲染轮播图就会出现问题。
  - 解决：等数据回来
    - watch 监听数据，数据初始化是空数据，数据一改变就说明数据回来了

  问题：还是不能无缝轮播
  - 原因：更新数据是同步的，更新用户界面是异步的，数据的确更新了，但是用户界面还未更新（涉及源码），此时还要执行同步代码，new Swiper，页面还未有图片，渲染出错。
  - 解决：等用户界面渲染完成，在 new Swiper
   - $nextTick(()=>{ new Swiper}) 

  解析：
  1.请求的时间是不确定的，页面渲染几遍请求未必回来
  2.数据回来才去渲染，new Swiper是拿到数据去轮播图片的，所以要先等到数据 
  3.因为父组件和子组件的生命周期顺序问题
    - 父beforeCreate  —— created —— beforeMount —— 子beforeCreate  —— created —— beforeMount—— 子mounted —— 父mounted
  4.子组件先 new Swiper（子mounted），此时请求都还未发送（父发送请求 父mounted），根本没有数据
  5.用watch监听数据一改变，说明imagesList有值了（有数据了）
  6.但是数据更新了，页面未更新 ，因为（数据更新是同步的，页面更新是异步的）
  7.此时还要执行同步代码，new Swiper，页面还未有图片，渲染出错
  8.使用$nextTick(()=>{ new Swiper}) 去等用户界面渲染完成，在 new Swiper

this.$nextTick
  简单理解：等用户界面更新完成，再触发回调函数
  真正理解：将回调函数添加到异步队列，等待将来执行
  如果是先更新数据，在调用 nextTick 方法的话
  先更新数据对应的更新用户界面的异步操作先进异步队列
  nextTick 方法的回调函数后进队列
  队列是先进先出的原则
  所以，先更新用户界面，再触发 nextTick 的回调

  轮播图 bug
  1. 问题一：Floor 组件中轮播图没法轮播
  根本原因：轮播图没有触发 watch，从而没有 new Swiper，就没有轮播的功能
  详细原因：
    - home 组件发送请求获取数据，遍历 Floor 组件展示
    - 一上来数据是空，Floor 组件没有展示
    - 后面请求得到数据，此时在遍历展示 Floor（初始化渲染），并且渲染时就有数据了
    - 作为 Floor 的子组件轮播图也是如此，一开始没有数据时没有渲染，有数据时就渲染
    - 对于轮播图组件，渲染时就已经有数据了，数据没有发生变化，就不会触发 watch

  解决：让监视属性第一次就要触发
    immediate: true, // 让监视属性第一次就触发

  2. 问题二：第一个轮播图触发了两次监视属性
  原因：
    - 第一个轮播图初始化渲染没有数据，（immediate: true）触发一次
    - 后面请求得到数据，数据发生变化，又触发一次
    - 触发两次就会 new 两次 Swiper，导致轮播出现 bug
  解决：只能 new 一次 Swiper
      if (!imageList.length) return; // 不进行第二次new Swiper 阻止第一次的（immediate: true）触发
  3. 问题三：所有轮播图还是有问题
  原因：所有轮播图共享同一个类名：`.swiper`, 导致 new Swiper 时对所有轮播图都生效了，就会有 bug
  解决：
    - 让每次 new Swiper，都只会自己生效
      - 方案一：取不同类名
      - 方案二：用 ref
        用不同类名未来还是有重复的风险，而 ref 不会
  - 给元素绑定 ref 属性
  - 在new Swiper中第一个参数使用元素
      new Swiper(this.$refs.swiperRef, {}}) // ref只能获取到自己组件的ref对应DOM元素，其他组件即使名称一致也是获取不到的
   

-->
